home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / BORLAND TURBO / OWLSRC.PAK / NOTETAB.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  19.3 KB  |  837 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.14  $
  6. //
  7. // Implementation of class TNoteTab
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_NOTETAB_H)
  11. # include <owl/notetab.h>
  12. #endif
  13. #if !defined(OWL_UIHELPER_H)
  14. # include <owl/uihelper.h>
  15. #endif
  16. #if !defined(OWL_COMMCTRL_H)
  17. # include <owl/commctrl.h>
  18. #endif
  19. #if !defined(WINSYS_UIMETRIC_H)
  20. # include <winsys/uimetric.h>
  21. #endif
  22.  
  23. OWL_DIAGINFO;
  24.  
  25. //
  26. // Constants used when drawing control
  27. //
  28. const int InitSize    = 5;        // Initial size of Tab Collection
  29. const int InitDelta   = 5;        // Inc. when expanding collection
  30. const int LabelMargin = 5;        // Pad on each side of tab label
  31. const int LabelVMargin= 1;        // Pad above/below the tab label
  32. const int TabMargin   = 4;        // Margin between two tabs
  33. const int CtrlMargin  = 5;        // Margin on each side of tab row
  34. const int CtrlVMargin = 1;        // Margin above row of tab
  35. const int HorzSelInc  = 2;        // Increment for selected tab
  36. const int VertSelInc  = 2;        // Increment for selected tab
  37.  
  38. //----------------------------------------------------------------------------
  39.  
  40. DEFINE_RESPONSE_TABLE1(TNoteTab, TControl)
  41.   EV_WM_SIZE,
  42.   EV_WM_LBUTTONDOWN,
  43.   EV_WM_GETDLGCODE,
  44.   EV_WM_KEYDOWN,
  45.   EV_WM_SETFOCUS,
  46.   EV_WM_KILLFOCUS,
  47. END_RESPONSE_TABLE;
  48.  
  49. //
  50. // Constructor of NoteTab object. Use this constructor when creating a
  51. // notetab control from scratch.
  52. //
  53. TNoteTab::TNoteTab(TWindow*   parent,
  54.                    int        id,
  55.                    int x, int y, int w, int h,
  56.                    TWindow*   buddy,
  57.                    bool       dialogBuddy,
  58.                    TModule*   module)
  59. :
  60.   TControl(parent, id, 0, x, y, w, h, module),
  61.   Buddy(buddy),
  62.   WindowFace(!dialogBuddy)
  63. {
  64.   InitCtrl();
  65. }
  66.  
  67. //
  68. // Constructor of Notetab object. Use this constructor when aliasing a
  69. // control defined within a dialog template.
  70. //
  71. TNoteTab::TNoteTab(TWindow*   parent,
  72.                    int        resourceId,
  73.                    TWindow*   buddy,
  74.                    bool       dialogBuddy,
  75.                    TModule*   module)
  76. :
  77.   TControl(parent, resourceId, module),
  78.   Buddy(buddy),
  79.   WindowFace(!dialogBuddy)
  80. {
  81.   InitCtrl();
  82. }
  83.  
  84. //
  85. // Destructor of NoteTab object - Clean up allocated resources.
  86. //
  87. TNoteTab::~TNoteTab()
  88. {
  89.   // Cleanup memory associated with notetab items
  90.   //
  91.   DeleteAll();
  92.  
  93.   // Cleanup font and tab item collection
  94.   //
  95.   delete TabFont;
  96.   delete TabList;
  97. }
  98.  
  99. //
  100. // Return the Window class name of the notetab control object
  101. //
  102. char far*
  103. TNoteTab::GetClassName()
  104. {
  105.   return OWL_NOTETAB;
  106. }
  107.  
  108. //
  109. // Overriden virtual of TWindow - Initialize font used by control and resize
  110. // accordingly.
  111. //
  112. void
  113. TNoteTab::SetupWindow()
  114. {
  115.   TControl::SetupWindow();
  116.  
  117.   SetupFont();
  118.  
  119.   // Scan here & update sizes now that we know the font
  120.   //
  121.   int cy = Attr.H = max(Attr.H, TabFont->GetHeight());
  122.   for (int i = 0; i < GetCount(); i++) {
  123.     SetTabSize(i);
  124.     TNoteTabItem& tab = *(*TabList)[i];
  125.     cy = max(cy, (int)tab.LabelSize.cy + CtrlVMargin*2 + LabelVMargin*2);
  126.   }
  127.   SetTabRects(FirstVisibleTab);
  128.  
  129.   // Add in the margin at the bottom and at the top if 3d
  130.   //
  131.   if (Style3d)
  132.     cy += TUIMetric::CyBorder*6 + TUIMetric::CySizeFrame;
  133.  
  134.   Attr.H = cy;
  135.   SetWindowPos(0, 0, 0, Attr.W, Attr.H, SWP_NOMOVE|SWP_NOACTIVATE|
  136.                                                      SWP_NOZORDER);
  137.  
  138.   // Initialize BuddyHandle if we have a Buddy.
  139.   //
  140.   if( Buddy )
  141.     BuddyHandle = Buddy->GetHandle();
  142. }
  143.  
  144. //
  145. // Add a new tabitem to the notetab control
  146. //
  147. int
  148. TNoteTab::Add(const char* label, uint32 clientData)
  149. {
  150.   return Insert(label, GetCount(), clientData);
  151. }
  152.  
  153. //
  154. // Insert a new tabitem at the specified index
  155. //
  156. int
  157. TNoteTab::Insert(const char* label, int index, uint32 clientData)
  158. {
  159.   PRECONDITION(index >= 0 && index <= GetCount());
  160.  
  161.   TabList->AddAt(new TNoteTabItem(label, clientData), index);
  162.  
  163.   SetTabSize(index);
  164.   SetTabRects(FirstVisibleTab);
  165.  
  166.   // Select [Could selection only if it's the first one inserted]
  167.   //
  168.   SetSel(index);
  169.  
  170.   // Return the index of the tab
  171.   //
  172.   return index;
  173. }
  174.  
  175. //
  176. // Remove the tabitem at the specified 'index'
  177. //
  178. bool
  179. TNoteTab::Delete(int index)
  180. {
  181.   // Validate index...
  182.   //
  183.   if (index < GetCount() && index >= 0) {
  184.  
  185.     // Mark rectangles that need to be redrawn
  186.     //
  187.     if (IsVisible(index)) {
  188.       for (int i = index; i < GetCount(); i++)
  189.         InvalidateTabRect(i);
  190.     }
  191.  
  192.     // Delete structure representing item
  193.     //
  194.     delete (*TabList)[index];
  195.     TabList->Detach(index);
  196.  
  197.     // Reset index of the first visible tab
  198.     //
  199.     if (index == FirstVisibleTab)
  200.       if (FirstVisibleTab != 0)
  201.         FirstVisibleTab--;
  202.     //
  203.     //
  204.     if (GetCount() > 0)
  205.       SetTabRects(FirstVisibleTab);
  206.     else
  207.       SelectedTab = -1;
  208.  
  209.     // Return success
  210.     //
  211.     return true;
  212.   }
  213.   return false;
  214. }
  215.  
  216. //
  217. // Remove all tab items in the notetab control
  218. //
  219. bool
  220. TNoteTab::DeleteAll()
  221. {
  222.   while (GetCount())
  223.     Delete(0);
  224.  
  225.   return true;
  226. }
  227.  
  228. //
  229. // Return the number of tab items in the notetab control
  230. //
  231. int
  232. TNoteTab::GetCount() const
  233. {
  234.   return TabList->Count();
  235. }
  236.  
  237. //
  238. // Return the index of the selected tabitem.
  239. // NOTE: Returns a zero-based index or -1 if there are no tab items
  240. //       in the notetab control.
  241. int
  242. TNoteTab::GetSel() const
  243. {
  244.   return SelectedTab;
  245. }
  246.  
  247. //
  248. // Select the tabitem at the specified index.
  249. // NOTE: SetSel does not send any notifications to the parent and/or buddy
  250. //
  251. int
  252. TNoteTab::SetSel(int index)
  253. {
  254.   if (index < GetCount() && index >= 0) {
  255.     if (index != SelectedTab) {
  256.  
  257.       // Invalidate area occupied by previously selected item
  258.       //
  259.       if (SelectedTab >= 0) {
  260.         InvalidateTabRect(SelectedTab);
  261.       }
  262.  
  263.       // Update selected index
  264.       //
  265.       SelectedTab = index;
  266.  
  267.       // Invalidate area occupied by new selection
  268.       //
  269.       if (SelectedTab >= 0) {
  270.         InvalidateTabRect(SelectedTab);
  271.       }
  272.     }
  273.     return index;
  274.   }
  275.   return -1;
  276. }
  277.  
  278. //
  279. // Retrieve information about the tab item at the specified index
  280. //
  281. bool
  282. TNoteTab::GetItem(int index, TNoteTabItem& tabItem) const
  283. {
  284.   PRECONDITION(index >= 0);
  285.   PRECONDITION(index < GetCount());
  286.  
  287.   tabItem = *(*TabList)[index];
  288.   return true;
  289. }
  290.  
  291. //
  292. // Update information about the tab item at the specified index
  293. //
  294. bool
  295. TNoteTab::SetItem(int index, const TNoteTabItem& tabItem)
  296. {
  297.   if (index < GetCount() && index >= 0) {
  298.     *(*TabList)[index] = tabItem;
  299.  
  300.     return true;
  301.   }
  302.   return false;
  303. }
  304.  
  305. //
  306. // Return handle of buddy window associated with the notetab control
  307. //
  308. HWND
  309. TNoteTab::GetBuddy() const
  310. {
  311.   return BuddyHandle;
  312. }
  313.  
  314. //
  315. // Set handle of the buddy window associated with this notetab control
  316. //
  317. void
  318. TNoteTab::SetBuddy(HWND hwnd)
  319. {
  320.   BuddyHandle = hwnd;
  321.   Buddy = GetWindowPtr( BuddyHandle );
  322.   if( !Buddy )
  323.     Buddy = new TWindow( hwnd );
  324. }
  325.  
  326. //
  327. // No transfers for NoteTab controls
  328. //
  329. uint
  330. TNoteTab::Transfer(void* /*buffer*/, TTransferDirection /*direction*/)
  331. {
  332.   return 0;
  333. }
  334.  
  335. //----------------------------------------------------------------------------
  336.  
  337. //
  338. // Initialize internal variables used by notetab
  339. //
  340. void
  341. TNoteTab::InitCtrl()
  342. {
  343.   // Initialize internal structures when using OWL's implementation
  344.   //
  345.   TabList = new TCVectorImp<TNoteTabItem*>(InitSize, InitDelta);
  346.   TabFont = 0;
  347.   SelectedTab = -1;
  348.   FirstVisibleTab = 0;
  349.  
  350.   // If on new shell, use 3d look by default, and add extra space for a margin
  351.   // at the top
  352.   //
  353.   if (TSystem::Has3dUI()) {
  354.     Style3d = true;
  355.     TopMargin = TUIMetric::CySizeFrame;
  356.   }
  357.   else {
  358.     Style3d = false;
  359.     TopMargin = 0;
  360.   }
  361.  
  362.   ScrollRect = TRect(0, 0, 0, 0);
  363.   SetBkgndColor(TColor::Sys3dFace);
  364. }
  365.  
  366. //
  367. // Invalidates the rectangle occupied by the tab at the specified index
  368. //
  369. void
  370. TNoteTab::InvalidateTabRect(int index)
  371. {
  372.   if (GetHandle()) {
  373.     TRect tbRect = (*TabList)[index]->Rect;
  374.     tbRect.Inflate(TabMargin, 1);
  375.     InvalidateRect(tbRect, true);
  376.   }
  377. }
  378.  
  379. //
  380. // Overriden Paint routine
  381. //
  382. void
  383. TNoteTab::Paint(TDC& dc, bool /*erase*/, TRect& /*rect*/)
  384. {
  385.   int i = GetCount();
  386.   if (i) {
  387.  
  388.     TRect clientRect;
  389.     GetClientRect(clientRect);
  390.  
  391.     // Create tools & select initial ones into the DC
  392.     //
  393.     TBrush faceBrush(TColor::Sys3dFace);
  394.  
  395.     // A pen with the active page color
  396.     //
  397.     TPen facePen((WindowFace && !Style3d) ?
  398.                   TColor::SysWindow : TColor::Sys3dFace);
  399.  
  400.     TPen hilitePen(TColor::Sys3dHilight);
  401.     TPen lightPen(TColor::Sys3dLight);
  402.     TPen edgePen(Style3d ? TColor::Sys3dShadow : TColor::SysWindowFrame);
  403.     TPen dkShadowPen(TColor::Sys3dDkShadow);
  404.  
  405.     dc.SelectObject(faceBrush);
  406.     dc.SelectObject(*TabFont);
  407.  
  408.     while (--i >= -1) {
  409.       // Skip the selected tab, it's drawn last. Otherwise get the
  410.       // working index
  411.       //
  412.       if (i == GetSel())
  413.         continue;
  414.       int ti = (i == -1) ? GetSel() : i;
  415.  
  416.       // Retrieve tab item information
  417.       //
  418.       TNoteTabItem& tab = *(*TabList)[ti];
  419.       TRect& tbRect = tab.Rect;
  420.  
  421.       // Draw border of tab
  422.       //
  423.       TPoint pt[4] = {                                // Corner points
  424.         TPoint(tbRect.left-TabMargin, tbRect.top-1),  // Top left
  425.         TPoint(tbRect.left, tbRect.bottom),           // Bottom left
  426.         TPoint(tbRect.right, tbRect.bottom),          // Bottom right
  427.         TPoint(tbRect.right+TabMargin, tbRect.top-1)  // Top right
  428.       };
  429.  
  430.       // If this is the selected tab...
  431.       //
  432.       if (i == -1) {
  433.          // If 3d, draw edge around
  434.          if (Style3d) {
  435.            clientRect.top += TUIMetric::CySizeFrame;
  436.            TUIBorder(clientRect, TUIBorder::WndRecessed).Paint(dc);
  437.          }
  438.          else {
  439.            // Dark line across top of tabs to the left of this one
  440.            dc.MoveTo(clientRect.left, pt[0].y);
  441.            dc.LineTo(tbRect.left-TabMargin, pt[0].y);
  442.            // Line across top of tabs to the right of this one
  443.            //
  444.            dc.MoveTo(pt[3].x, pt[3].y);
  445.            dc.LineTo(clientRect.right, pt[3].y);
  446.          }
  447.       }
  448.  
  449.       // In 3-d mode, draw all in face, w/ hilite
  450.       //
  451.       if (Style3d) {
  452.         dc.SelectObject(facePen);          // draw tab w/ face
  453.         dc.Polygon(pt, COUNTOF(pt));
  454.  
  455.         dc.SelectObject(lightPen);         // inside left
  456.         dc.MoveTo(pt[0].x+1, pt[0].y);
  457.         dc.LineTo(pt[1].x+1, pt[1].y);
  458.  
  459.         dc.SelectObject(edgePen);          // inside bottom & right
  460.         dc.MoveTo(pt[1].x+1, pt[1].y-1);
  461.         dc.LineTo(pt[2].x-1, pt[2].y-1);
  462.         dc.LineTo(pt[3].x-1, pt[3].y);
  463.  
  464.         dc.SelectObject(hilitePen);        // outside left
  465.         dc.MoveTo(pt[0].x, pt[0].y);
  466.         dc.LineTo(pt[1].x, pt[1].y);
  467.  
  468.         dc.SelectObject(dkShadowPen);      // outside bottom & right
  469.         dc.LineTo(pt[2].x, pt[2].y);
  470.         dc.LineTo(pt[3].x, pt[3].y);
  471.         dc.RestorePen();
  472.       }
  473.       // In WindowFace mode, draw selected tab in window color
  474.       //
  475.       else if (i == -1 && WindowFace) {
  476.         TBrush windowBrush(TColor::SysWindow);
  477.         dc.SelectObject(facePen);
  478.         dc.SelectObject(windowBrush);
  479.         dc.Polygon(pt, COUNTOF(pt));
  480.         dc.RestoreBrush();
  481.         dc.RestorePen();
  482.         dc.Polyline(pt, COUNTOF(pt));
  483.       }
  484.       else {
  485.         dc.SelectObject(facePen);
  486.         dc.Polygon(pt, COUNTOF(pt));
  487.         dc.RestorePen();
  488.         dc.Polyline(pt, COUNTOF(pt));
  489.       }
  490.  
  491.       // Draw tab label
  492.       //
  493.       dc.SetBkMode(TRANSPARENT);
  494.       dc.DrawText(tab.Label.c_str(), -1, tbRect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  495.  
  496.       // If the note tab has input focus, draw the focus rectangle
  497.       //
  498.       if (i == -1 && GetFocus() == GetHandle()) {
  499.           DrawFocusRect(dc);
  500.       }
  501.     }
  502.  
  503.     dc.RestoreBrush();
  504.     dc.RestoreFont();
  505.   }
  506. }
  507.  
  508. //
  509. // WM_SIZE handler - Relay tab items
  510. //
  511. void
  512. TNoteTab::EvSize(uint sizeType, TSize& size)
  513. {
  514.   TControl::EvSize(sizeType, size);
  515.  
  516.   // Layout tab items
  517.   //
  518.   SetTabRects(FirstVisibleTab);
  519. }
  520.  
  521. //
  522. // WM_LBUTTONDOWN handler -
  523. //
  524. void
  525. TNoteTab::EvLButtonDown(uint /*modKeys*/, TPoint& point)
  526. {
  527.   int hitIndex = TabFromPoint(point);
  528.   if (hitIndex != -1) {
  529.     NotifyAndSelect(hitIndex);
  530.   }
  531.  
  532.   // Grab focus
  533.   SetFocus();
  534. }
  535.  
  536. //
  537. // Handle WM_SETFOCUS: Draw focus to identify selected tab
  538. //
  539. void
  540. TNoteTab::EvSetFocus(THandle hWndLostFocus)
  541. {
  542.   TControl::EvSetFocus(hWndLostFocus);
  543.   DrawFocusRect(TClientDC(*this));
  544. }
  545.  
  546. //
  547. // Handle WM_KillFOCUS: Remove dotted focus rectangle from selected tab
  548. //
  549. void
  550. TNoteTab::EvKillFocus(THandle hWndGetFocus)
  551. {
  552.   TControl::EvKillFocus(hWndGetFocus);
  553.   DrawFocusRect(TClientDC(*this));
  554. }
  555.  
  556. //
  557. // Draw a dashed rectangle around the selected tab if it has input focus.
  558. // calling this function a second time for the same tab erases the
  559. // rectangle.
  560. //
  561. void
  562. TNoteTab::DrawFocusRect(TDC& dc)
  563. {
  564.   if (GetCount() > 0 && GetSel() >= 0) {
  565.  
  566.     // Set the appropriate background color so the the focus rectangle
  567.     // will erase cleanly.
  568.     //
  569.     // Setting color here is redundant when called from Paint, because
  570.     // Windows sets the background color for the Paint DC.  Windows does
  571.     // not set it, however, for the DC passed to SetFocus and KillFocus.
  572.     //
  573.     dc.SetBkColor(TColor::Sys3dFace);
  574.  
  575.     // Calculate coordinates and draw the focus rectangle
  576.     //
  577.     TRect selectedRect = (*TabList)[GetSel()]->Rect;
  578.     selectedRect.Inflate(-HorzSelInc, -VertSelInc);
  579.     dc.DrawFocusRect(selectedRect);
  580.   }
  581. }
  582.  
  583. //
  584. // WM_GETDLGCODE handler - Inform dialog manager that we want to handle
  585. // arrow keys
  586. //
  587. uint
  588. TNoteTab::EvGetDlgCode(MSG far* msg)
  589. {
  590.   return TControl::EvGetDlgCode(msg) | DLGC_WANTARROWS;
  591. }
  592.  
  593. //
  594. // WM_KEYDOWN handler - handle arrow keys to allow user to navigate
  595. // through tab items
  596. //
  597. void
  598. TNoteTab::EvKeyDown(uint key, uint /*repeatCount*/, uint /*flags*/)
  599. {
  600.   int tab = GetSel();
  601.  
  602.   // right arrow key pressed
  603.   //
  604.   if (key == VK_RIGHT) {
  605.     if (tab == GetCount() - 1)    // is selected tab already at the left end?
  606.       return;
  607.     else
  608.       NotifyAndSelect(++tab);
  609.   }
  610.  
  611.   // left arrow key pressed
  612.   //
  613.   if (key == VK_LEFT) {
  614.     if (tab == 0)                 // is selected tab already at the right end?
  615.       return;
  616.     else
  617.       NotifyAndSelect(--tab);
  618.   }
  619. }
  620.  
  621. //
  622. // Update the internal information stored about the label of a particular
  623. // tab item.
  624. //
  625. void
  626. TNoteTab::SetTabSize(int index)
  627. {
  628.   if (TabFont) {
  629.     // Use screen DC (may be called before 'HWND') & selected font
  630.     //
  631.     TScreenDC dc;
  632.     dc.SelectObject(*TabFont);
  633.  
  634.     // Compute size of label
  635.     //
  636.     TNoteTabItem& tab = *(*TabList)[index];
  637.     dc.GetTextExtent(tab.Label.c_str(), tab.Label.length(), tab.LabelSize);
  638.     dc.RestoreFont();
  639.   }
  640. }
  641.  
  642. //
  643. // Layout tab items with the specified index at the leftmost.
  644. //
  645. void
  646. TNoteTab::SetTabRects(int firstTab)
  647. {
  648.   // First hide the tabs preceeding the first one
  649.   //
  650.   for (int i = 0; i < firstTab; i++) {
  651.     TRect& tbRect = (*TabList)[i]->Rect;
  652.  
  653.     if (!tbRect.IsNull()) {
  654.       InvalidateTabRect(i);
  655.       tbRect.SetNull();
  656.     }
  657.   }
  658.  
  659.   // Retrieve the area where tabs can hang out
  660.   //
  661.   TRect tabArea;
  662.   GetTabsArea(tabArea);
  663.  
  664.   // Loop vars to keep track of upper left corner assignments
  665.   //
  666.   int x = tabArea.left;
  667.   int y = tabArea.top;
  668.  
  669.   // 3d tabs need extra room for 3d edges
  670.   //
  671.   int edgeVMargin = Style3d ? GetSystemMetrics(SM_CYBORDER)*2 : 0;
  672.  
  673.   // Iterate through each tab
  674.   //
  675.   int index;
  676.   for (index = firstTab; index < GetCount(); index++) {
  677.     TNoteTabItem& tab = *(*TabList)[index];
  678.     TRect& tbRect = tab.Rect;
  679.  
  680.     // If tab is completely off viewport, break;
  681.     //
  682.     if (x-TabMargin >= tabArea.right)
  683.       break;
  684.  
  685.     // Compute tab's width with margins
  686.     //
  687.     int tabWidth1 = tab.LabelSize.cx + LabelMargin*2;
  688.  
  689.     // Compute new rectangle
  690.     //
  691.     TRect newRect(x+TabMargin, y, x+TabMargin+tabWidth1,
  692.                   y+tab.LabelSize.cy+LabelVMargin*2+edgeVMargin);
  693.  
  694.     // Set left side of next tab
  695.     //
  696.     x += tabWidth1+TabMargin;
  697.  
  698.     // Invalidate rectangle(s) and assign new area to tab
  699.     //
  700.     if (tbRect != newRect) {
  701.       if (!tbRect.IsNull())
  702.         InvalidateTabRect(index);
  703.  
  704.       tbRect = newRect;
  705.  
  706.       // Force new rectangle to be repainted
  707.       //
  708.       if (!tbRect.IsNull())
  709.         InvalidateTabRect(index);
  710.     }
  711.   }
  712.  
  713.   // Hide any remaining tabs
  714.   //
  715.   while (index < GetCount()) {
  716.     TNoteTabItem& tab = *(*TabList)[index];
  717.     TRect& tbRect = tab.Rect;
  718.  
  719.     if (!tbRect.IsNull())
  720.       InvalidateTabRect(index);
  721.  
  722.     tbRect.SetNull();
  723.     index++;
  724.   }
  725. }
  726.  
  727. //
  728. // Set the specified font handle as the one to be used when drawing the
  729. // labels of tab items.
  730. //
  731. void
  732. TNoteTab::SetupFont(HFONT font)
  733. {
  734.   if (font == 0) {
  735.     // Try to get our parent's font
  736.     //
  737.     if (Parent && Parent->GetHandle())
  738.       font = Parent->GetWindowFont();
  739.       
  740.     // Use the default UI font
  741.     //
  742.     if (!font) {
  743.       LOGFONT lf;
  744.       TDefaultGUIFont().GetObject(lf);
  745.       font = CreateFontIndirect(&lf);
  746.     }
  747.   }
  748.  
  749.   if (font)
  750.     TabFont = new TFont(font);
  751. }
  752.  
  753. //
  754. // Return the index of the tab item at the specified window coordinate
  755. //
  756. int
  757. TNoteTab::TabFromPoint(const TPoint& pt)
  758. {
  759.   for (int i = 0; i < GetCount(); i++) {
  760.     if ((*TabList)[i]->Rect.Contains(pt))
  761.       return i;
  762.   }
  763.   return -1;
  764. }
  765.  
  766. //
  767. // Select a tab and send the appropriate notifications
  768. //
  769. void
  770. TNoteTab::NotifyAndSelect(int index)
  771. {
  772.   PRECONDITION(index >= 0);
  773.   PRECONDITION(index < GetCount());
  774.  
  775.   // First notify that we're about to change selection
  776.   //
  777.   TNotify not(*this, Attr.Id, TCN_SELCHANGING);
  778.   if (!SendNotification(::GetParent(*this), Attr.Id, not)) {
  779.  
  780.     // If notification was not vetoed, proceed...
  781.     //
  782.     SetSel(index);
  783.  
  784.     // Notify of selection change to the buddy if one, otherwise
  785.     // the parent.
  786.     //
  787.     not.code = TCN_SELCHANGE;
  788.     if( Buddy )
  789.       SendNotification( BuddyHandle, Attr.Id, not);
  790.     else
  791.       SendNotification(::GetParent(*this), Attr.Id, not);
  792.   }
  793. }
  794.  
  795. //
  796. // Retrieve  the desired location of the scrollers within the tab
  797. //
  798. void
  799. TNoteTab::GetScrollerArea(TRect& rect)
  800. {
  801.   PRECONDITION(GetCount() > 0);
  802.  
  803.   // Retrieve area tabs hang in
  804.   //
  805.   GetTabsArea(rect);
  806.  
  807.   // Shrink area to match tabs height with a width twice as big
  808.   //
  809.   rect.left = rect.right - rect.Height()*2;
  810. }
  811.  
  812. //
  813. // Retrieve the rectangle within tabs lie. If there are no tabs in the
  814. // control, then only the left, top and right sides are valid as the bottom
  815. // requires tabs to be computed
  816. //
  817. void
  818. TNoteTab::GetTabsArea(TRect& rect)
  819. {
  820.   // First retrieve left, top and right borders
  821.   //
  822.   GetClientRect(rect);
  823.   rect.Inflate(-CtrlMargin, -CtrlVMargin);
  824.   rect.top += TopMargin;
  825. }
  826.  
  827. //
  828. // Return true if the tab item at the specified index is visible. Returns
  829. // false otherwise.
  830. //
  831. bool
  832. TNoteTab::IsVisible(int index) const
  833. {
  834.   PRECONDITION(index < GetCount() && index >= 0);
  835.   return (*TabList)[index]->Rect.IsNull() ? false : true;
  836. }
  837.